package com.xsir.common;

import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.ShiroException;
import org.apache.shiro.authz.UnauthenticatedException;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * @author user
 * @date 2020/9/4
 *
 * 全局异常处理类
 * 使用 slf4j 保存日志信息，Result包装异常信息
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    /**
     * Shiro异常
     *
     * @param e ShiroException实例
     * @return  结果
     */
    @ExceptionHandler(ShiroException.class)
    public ResponseEntity<?> handleShiroException(HttpServletRequest request, ShiroException e) {
        log.error("---------认证异常---------");
        
        String errorMsg;
        HttpStatus status = getStatus(request);
        if(e instanceof UnauthenticatedException) {
            errorMsg = "请先登录！";
        } else if(e instanceof UnauthorizedException) {
            errorMsg = "权限不足！";
        } else {
            errorMsg = e.getMessage();
        }
        
        Map<String, Object> responseMap = new HashMap<>(2);
        responseMap.put("message", errorMsg);
        responseMap.put("code", 401);
        return new ResponseEntity<Object>(responseMap,HttpStatus.OK);
    }
    
    @ExceptionHandler(ServletException.class)
    public ResponseEntity<?> handleServletException(HttpServletRequest request, Exception e) {
        HttpStatus status = getStatus(request);
        Map<String, Object> responseMap = new HashMap<>(2);
        responseMap.put("message", e.getMessage());
        responseMap.put("code", status.value());
        return new ResponseEntity<Object>(responseMap, HttpStatus.OK);
    }
    
    @ExceptionHandler(NoHandlerFoundException.class)
    public ResponseEntity<?> handleNoHandlerFoundException(Exception e) {
        Map<String, Object> responseMap = new HashMap<>(2);
        responseMap.put("message", e.getMessage());
        responseMap.put("code", 404);
        return new ResponseEntity<Object>(responseMap,HttpStatus.NOT_FOUND);
    }
    
    /**
     * 获取请求状态码
     * @param request 状态码
     * @return        HttpStatus
     */
    private HttpStatus getStatus(HttpServletRequest request) {
        Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
        if(statusCode == null) {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
        return HttpStatus.valueOf(statusCode);
    }
}
